package org.jeecg.config;

import org.jeecg.common.util.SpringContextUtils;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.ee.servlet.QuartzInitializerListener;
import org.quartz.spi.JobFactory;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.util.List;
import java.util.Properties;

/**
 * @author: zhengdc
 * @date: 2019/12/6
 * @description: quartz 自定义配置类
 */
@Configuration
public class QuartzConfig {
    public static final String QUARTZ_PROPERTIES_PATH = "/quartz.properties"; //自定义配置quartz路径：主要是自定义表名前缀

    @Autowired
    private DataSource dataSource; //指向项目数据库，不再需要配置数据库

    @Autowired(required = false)
    private List<Trigger> triggers;

    @Bean
    public JobFactory jobFactory(ApplicationContext applicationContext) {
        org.jeecg.config.QuartzConfig.AutowiringSpringBeanJobFactory jobFactory = new org.jeecg.config.QuartzConfig.AutowiringSpringBeanJobFactory();
        jobFactory.setApplicationContext(applicationContext);
        return jobFactory;
    }

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory) throws IOException {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        // 设置dataSource 跟项目使用同一个dataSource，会覆盖quartz.properties里面的配置
        factory.setDataSource(dataSource);
        //可选,QuartzScheduler启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录
        factory.setOverwriteExistingJobs(true); //覆盖之前未停止的任务
        factory.setAutoStartup(true);
        factory.setQuartzProperties(quartzProperties());
        factory.setStartupDelay(2);// 在SchedulerFactoryBean初始化完成后，延迟多少秒启动Scheduler，默认为0，表示马上启动。
        factory.setJobFactory(jobFactory);
        return factory;
    }

    @Bean
    public Properties quartzProperties() throws IOException {
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        propertiesFactoryBean.setLocation(new ClassPathResource(QUARTZ_PROPERTIES_PATH));
        propertiesFactoryBean.afterPropertiesSet();
        return propertiesFactoryBean.getObject();
    }

    public static class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements
            ApplicationContextAware {

        private transient AutowireCapableBeanFactory beanFactory;

        @Override
        public void setApplicationContext(final ApplicationContext context) {
            beanFactory = context.getAutowireCapableBeanFactory();
        }

        @Override
        protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
            final Object job = super.createJobInstance(bundle);
            beanFactory.autowireBean(job);
            return job;
        }
    }
}